/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.edit.command;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.uml2.uml.Element;

import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

/**
 * Command to select a part on a diagram. Input: o AnyEditPart o Target: the element to be
 * selected o selectForEdit: if true, a DirectEditRequest will be directed to the element
 * Output: None
 * 
 * @author frankd
 */
public class SelectPartCommand extends Command {
    private EditPart anyEditPart;
    private Element target;
    private boolean selectForEdit;

    private ISelection oldSelection;

    public void setAnyEditPart(final EditPart anyEditPart) {
        this.anyEditPart = anyEditPart;
    }

    public void setSelectForEdit(final boolean selectForEdit) {
        this.selectForEdit = selectForEdit;
    }

    public void setTarget(final Element target) {
        this.target = target;
    }

    public void execute() {
        new UIJob("Select element") {
            public IStatus runInUIThread(final IProgressMonitor progress) {
                Object anyEPModel = anyEditPart.getModel();
                if (!(anyEPModel instanceof GraphElement))
                    return Status.OK_STATUS;
                if (((GraphElement) anyEPModel).getContainer() != null) {
                    Diagram diagram = LookForElement.getDiagram((GraphElement) anyEPModel);
                    if (diagram == null)
                        return Status.OK_STATUS;

                    GraphElement targetView = ModelUtil.getGraphElement(target, diagram);
                    if (targetView == null)
                        return Status.OK_STATUS;

                    final EditPart targetEP =
                            (EditPart) anyEditPart.getViewer().getEditPartRegistry()
                                    .get(targetView);
                    if (targetEP == null)
                        return Status.OK_STATUS;

                    oldSelection = anyEditPart.getViewer().getSelection();
                    anyEditPart.getViewer().select(targetEP);

                    if (selectForEdit) {
                        DirectEditRequest editReq = new DirectEditRequest();
                        if (targetEP instanceof GraphicalEditPart)
                            editReq.setLocation(getEditLocation((GraphicalEditPart) targetEP));
                        targetEP.performRequest(editReq);
                    }
                }
                return Status.OK_STATUS;
            }
        }.schedule();
    }

    protected Point getEditLocation(GraphicalEditPart editPart) {
        return editPart.getFigure().getBounds().getLocation();
    }

    public void undo() {
        new UIJob("Select element") {
            public IStatus runInUIThread(final IProgressMonitor progress) {
                // anyEditPart.getViewer().setSelection(oldSelection);
                return Status.OK_STATUS;
            }
        }.schedule();
    }

    private void red() {
        execute();
    }

    /**
     * @see org.eclipse.gef.commands.Command#redo()
     */
    @Override
    public void redo() {
        this.execute();
    }
}
